package org.budo.dubbo.protocol.async.util;

import org.budo.dubbo.protocol.async.repository.BudoAsyncInvocation;
import org.budo.time.Time;

import com.alibaba.dubbo.rpc.Invoker;

import lombok.extern.slf4j.Slf4j;

/**
 * @author lmw
 */
@Slf4j
public class AsyncLogUtil {
    private static final String TIME_FORMAT = "yyyyMMdd.HHmmss.SSS";

    /**
     * 消息延迟超过5秒打info日志
     */
    public static final long MAX_MESSAGE_DELAY_INFO = 5 * 1000;

    /**
     * 消息延迟超过20秒打warn日志
     */
    public static final long MAX_MESSAGE_DELAY_WARN = 20 * 1000;

    /**
     * 消息延迟超过60秒打error日志
     */
    public static final long MAX_MESSAGE_DELAY_ERROR = 60 * 1000;

    private static long _LAST_TRACE_LOG_TIME;

    /**
     * 如果消息延迟就打日志
     * 
     * @param destinationName
     * 
     * @param _this
     */
    public static void logMessageDelay(BudoAsyncInvocation budoAsyncInvocation, String destinationName, Invoker<?> invoker, Object _this) {
        if (null == budoAsyncInvocation) {
            log.error("#61 budoAsyncInvocation=" + budoAsyncInvocation + ", destinationName=" + destinationName + ", invoker=" + invoker + ", this=" + _this);
            return;
        }

        Long createdAt = budoAsyncInvocation.getCreatedAt();
        if (null == createdAt) {
            log.debug("#66 createdAt is null, budoAsyncInvocation=" + budoAsyncInvocation + ", destinationName=" + destinationName + ", invoker=" + invoker + ", this=" + _this);
            return;
        }

        long now = System.currentTimeMillis();
        long messageDelay = now - createdAt; // 消息延迟时间

        // 后发先至，时间不准？
        String message = "MESSAGE_DELAY, now=" + Time.when(now).toString(TIME_FORMAT) //
                + ", createdAt=" + Time.when(createdAt).toString(TIME_FORMAT) //
                + ", messageDelay=" + messageDelay + " ms" //
                + ", destinationName=" + destinationName //
                + ", interface=" + invoker.getInterface() //
                + ", methodName=" + budoAsyncInvocation.getMethodName() //
                + ", this=" + _this;

        if (messageDelay < 0) {
            log.error("#79 " + message);
            return;
        }

        // 耗时较少，不打日志
        if (messageDelay < MAX_MESSAGE_DELAY_INFO) {
            log.debug("#72 " + message);
            return; // 小于info 打 debug
        }

        if (messageDelay < MAX_MESSAGE_DELAY_WARN) {
            log.info("#89 " + message); // 小于 warn 打 info
            return;
        }

        if (messageDelay < MAX_MESSAGE_DELAY_ERROR) {
            log.warn("#94 " + message); // 小于 error 打 warn
            return;
        }

        log.error("#82 " + message); // 打error
    }

    /**
     * ERROR 日志 每分钟打一次 避免太多
     */
    public static void error(String message, Throwable e) {
        long now = System.currentTimeMillis();

        if (_LAST_TRACE_LOG_TIME < now - 60 * 1000) {
            log.error(message + ", e=" + e, e);
        } else {
            log.error(message + ", e=");
        }
    }
}
